#include "GEnginePCH.h"
#include "Model.h"
#include "Support.h"

Model::Model(void)
{

}
Model::Model( char *filename )
{	
	LoadModel(filename);	
}

Model::~Model(void)
{
	this->DeleteModel();
}
int Model::LoadModel( char *filename)
{
	LPD3DXBUFFER matbuffer;
	HRESULT result;


	//load mesh from the specified file
	result = D3DXLoadMeshFromX(
		filename,               //filename
		D3DXMESH_DYNAMIC,     //mesh options
		d3ddev,                 //Direct3D device
		NULL,                   //adjacency buffer
		&matbuffer,             //material buffer
		NULL,                   //special effects
		&this->material_count, //number of materials
		&this->mesh);          //resulting mesh

	if (result != D3D_OK)
	{
		MessageBox(NULL, "Error loading model file ", filename, MB_OK);
		return -1;
	}

	//extract material properties and texture names from material buffer
	LPD3DXMATERIAL d3dxMaterials = (LPD3DXMATERIAL)matbuffer->GetBufferPointer();



	materials = new D3DMATERIAL9[material_count];


	textures  = new LPDIRECT3DTEXTURE9[material_count];


	//create the materials and textures
	for(DWORD i=0; i<material_count; i++)
	{
		//grab the material
		materials[i] = d3dxMaterials[i].MatD3D;

		//set ambient color for material 
		materials[i].Ambient = materials[i].Diffuse;

		textures[i] = NULL;
		if( d3dxMaterials[i].pTextureFilename != NULL && 
			lstrlen(d3dxMaterials[i].pTextureFilename) > 0 )
		{	
			char pathfile[256];
			sprintf_s(pathfile,"../data/%s", d3dxMaterials[i].pTextureFilename);
		
			//load texture file specified in .x file
			result = D3DXCreateTextureFromFile(d3ddev, 
				pathfile, 
				&textures[i]);
			

			if (result != D3D_OK)
			{
				char c[256];
				sprintf_s(c,"Could not find texture file : %s", d3dxMaterials[i].pTextureFilename);

				MessageBox(NULL, c, "Error", MB_OK);
				return NULL;
			}
		}
	}

	//done using material buffer
	matbuffer->Release();

	return 0;
}

void Model::DeleteModel(void)
{
	//remove materials from memory
	if( materials != NULL ) 
		delete[] materials;
	
	//remove textures from memory
	if (textures != NULL)
	{
		MessBox("nu=i null");
		for( DWORD i = 0; i < material_count; i++ )
		{
			if ( textures[i] != NULL )
				textures[i]->Release();
		}
	
		delete[] textures;
	}

	//remove mesh from memory
	if ( mesh != NULL )
		mesh->Release();

	//remove model struct from memory
	if ( this != NULL )
		free(this);

}

void Model::Render()
{
	//draw each mesh subset
	for( DWORD i=0; i<material_count; i++ )
	{
		// Set the material and texture for this subset
		d3ddev->SetTexture( 0, textures[i] );

		// Draw the mesh subset
		mesh->DrawSubset( i );
	}
}
void Model::invalidateDeviceObjects(void)
{
    if( mesh != NULL )
    {
        int nNewRefCount = mesh->Release();
	
        if( nNewRefCount > 0 )
        {
            static char strError[255];
            sprintf_s( strError, "The mesh object failed to cleanup properly.\n"
                "Release() returned a reference count of %d", nNewRefCount );
            MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
        }

        mesh = NULL;
    }  
	
	
	//remove textures from memory
	if (textures != NULL)
	{
		int nNewRefCount = 0;
		
		for( DWORD i = 0; i < material_count; i++ )
		{
			if ( textures[i] != NULL )
				nNewRefCount = textures[i]->Release();
		}

        if( nNewRefCount > 0 )
        {
            static char strError[255];
            sprintf_s( strError, "The textures of the mesh object failed to cleanup properly.\n"
                "Release() returned a reference count of %d", nNewRefCount );
            MessageBox( NULL, strError, "ERROR", MB_OK | MB_ICONEXCLAMATION );
        }
		delete[] textures;
        textures = NULL;
    }

}
LPD3DXMESH Model::getMesh(void)
{
	return mesh;
}
void Model::SetMinBounds(const D3DXVECTOR3& val)
{
	minB = val; 
}
void Model::SetMaxBounds(const D3DXVECTOR3& val)
{
	maxB = val; 
}